/**
 * 模版语法
 *
 * template -》 HTML字符串 -》 存在Vue特性 -》 表达式/属性/指令
 *
 * Vue的模版都基于HTML
 *
 * 模版中直接写HTML都是能够被HTML解析器解析的
 *
 * Vue ——》 表达式/自定义属性/指令
 *
 * Vue 一套模版编译系统
 *
 * 开发者写的template -》分析 HTML 字符串 -》 生成 AST 树 -》 解析 表达式/自定义属性/指令
 * -》 虚拟DOM树 -》 真实DOM树 -》 render
 */

/**
 * 插值
 *
 * Mustache
 * 
 * Vue 核心库中视图与数据联动只有两种方式
 * 1. 通过 data 数据变更
 * 2. 通过 props 传递变更
 */

// import Mustache from 'mustache'

// var data = {
//   title: 'This is my title for mustache'
// }

// var html = Mustache.render(
//   `<h1>{{ title }}</h1>`,
//   data
// )

// document.getElementById('app').innerHTML = html

import { remove } from '@vue/shared'
import { h, createApp } from 'vue'

// const Title = {
//   props: {
//     title: String
//   },
//   template: `
//     <h1>{{ title }} from App</h1>
//   `
// }

// const App = {
//   data() {
//     return {
//       title: 'This is my title',
//       auther: 'wgf',
//       dateTime: new Date(),
//       content: "This is my Content"
//     }
//   },
//   components: {
//     Title
//   },
//   template: `
//     <div>
//       <Title :title="title" />
//       <p>
//         <span class="auther">{{ auther }}</span> - {{ dateTime }}
//       </p>
//       <p :title="content">{{ content }}</p>
//       <button @click="changeTitle">Change Title</button>
//     </div>
//   `,
//   methods: {
//     changeTitle () {
//       this.title = 'this is App Title'
//     }
//   }
//   // render() {
//   //   return h(
//   //     'div',
//   //     {},
//   //     [
//   //       h('h1', { class: 'title' }, this.title),
//   //       h('p', {},
//   //         [
//   //           h('span', { class: 'auther' }, this.auther),
//   //           `- ${this.dateTime}`
//   //         ]
//   //       ),
//   //       h('p', { title: this.content }, this.content)
//   //     ]
//   //   )
//   // }
// }

// ----------------------------------------

/**
 * 指令
 * 
 * 所有在Vue中，模版上属性的【v-*】都是指令
 * 
 * 为什么叫指令？
 * 模版应该按照这样的逻辑进行渲染或绑定行为
 * 
 * Vue 提供了大量的内置指令 v-if v-else v-html v-for v-show v-html v-once
 * 开发者也可以给 Vue 扩展指令 -> 自定义指令  v-取名
 * 
 * v-once 一次差值，不用更新（不建议这么做）
 * 
 */

// const TITLE = 'This is out title' // 替代 v-once 方案

// const App = {
//   data () {
//     return {
//       title: 'This is my title',
//       author: 'wgf'
//     }
//   },
//   // 视图上的 Vue指定的插入方式的数据（Mustache） 变量必须声明在实例上
//   template: `
//     <div>
//       <h1 v-once>{{ title }} - {{ author }}</h1>
//       <button @click="changTitle">Change Title</button>
//     <div>
//   `,
//   methods: {
//     changeTitle () {
//       this.title = 'This is your title'
//       this.author = 'tfjy'
//     }
//   }
// }

/**
 * v-html
 * 差值不会解析HTML（安全考虑），因为差值是JS表达式，没有对DOM的操作  rawHTML（纯HTML）
 * 
 * 不要试图用 v-html 做子模版, vue 本身有一个底层的模版编译系统，
 * 而非直接使用的字符串渲染的
 * 子模版应该放在子组件中，让模版的重用和组合更强大
 * 也不要将用户提供的内容作为 v-html 的插值，容易导致XSS攻击
 * 
 * v-html 动态的渲染HTML，使用基本是innerHTML
 * 
 * innerHTML 有时候会容易导致XSS攻击
 */

// const App = {
//   data () {
//     return {
//       title: '<h1>This is my title</h1>'
//     }
//   },
//   template: `
//     <div v-html="title">
//       {{ title }}
//     </div>
//   `
// }

// var text = '<script>alert(123)</script>' // HTML5 帮忙禁止了
// var text = '<img src="123" onerror="alert(123)">'
// document.getElementById('app').innerHTML = text

/**
 * 属性
 *
 * attribute：一般指 HTML 的扩展（例如：title、src、href）【简写：attr】
 * property：（数据层面）在对象内部存储数据，通常用来描述数据结构  【简写：prop】
 *
 * Mustache 中是不支持在HTML属性中插值的
 * Vue 中因为用底层的模版编译系统，支持 Vue 内置的属性
 *
 * v-bind -> v-bind:id <=> id 变量
 *
 * var title = 't'
 * <h1 v-bind:id='title' :id='title'></h1>
 * <h1 id='t'></h1>
 *
 * 要在 HTML 中插入 JS的表达式，需要用 v-bind
 * 
 * 标签上插入 {{}}， 属性上 v-bind:XXX = 'value'
 */

// const App = {
//   data() {
//     return {
//       imgUrl: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F5%2F5476e32631957.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670503767&t=5874b7088a3d21127c038e0921872337',
//       title: '标题',
//       content: '内容',
//       isLogin: false
//     }
//   },
//   template: `
//     <article>
//       <h1>{{ title }}</h1>
//       <div>
//         <img :src='imgUrl' width='50' height='50' />
//       </div>
//       <p :title="content" :id='null' :class="undefined">
//         {{ content }}
//       </p>
//       <p>
//         <textarea :disabled='!isLogin' placeholder="请写评论"></textarea>
//       </p>
//     </article>
//   `
// }

/**
 * disabled=""
 * 对于模版解析， true是一个字符串，并不是逻辑真
 * :disabled="true" 逻辑真
 */

/**
 * truthy   falsy
 * falsy: false 0 "" null undefined NaN 的集合
 * truthy: 除以上外的其他
 * 
 * 对于 disable 逻辑真假的属性来说
 * 
 * 只有 true false "" 和 truthy 会在解析过程中将 disabled 属性包含在元素 上
 */

/**
 * 插值 -》 JS表达式 （！！！不是语句、模块、函数、赋值、声明）
 * 一个插值只能有一个表达式
 * 
 * var a => 声明语句
 * var a = 1 => 声明赋值语句
 * a = 1 => 赋值表达式
 */

// var App = {
//   data () {
//     return {
//       a: 1,
//       b: 2,
//       title: 'MAIN TITLE',
//       subTitle: 'SUB TITLE'
//     }
//   },
//   template: `
//     <!-- 数学运算表达式 -->
//     <h1 :title="a + b">{{ a + b }}</h1>
//     <!-- 字符串拼接 -->
//     <h2>{{ 'a + b = ' + (a + b) }}</h2>
//     <!-- 判断if语句（报错） -->
//     <h3>{{ if(a + b > 5) { return '大于5' } else { return '小于等于5' } }}</h3>
//     <h3>{{ a + b > 5 ? '大于5' : '小于等于5' }}</h3>
//     <!-- 逻辑表达式 -->
//     <h3>{{ title || subTitle }}</h3>
//     <h3>{{ title && subTitle }}</h3>
//     <!-- 使用JS API -->
//     <h4>{{ title.replace('MAIN ', 'first') }}</h4>
//     <h4>{{ subTitle.split('').reverse().join('-') }}</h4>
//     <!-- 绑定多个表达式 (错误) -->
//     <h5>
//       {{
//         a + b > 5 ? '大于5' : '小于等于5';
//         title
//       }}
//     </h5>
//     <!-- 声明赋值语句    赋值表达式-->
//     {{ var a = 1 }}{{ a = 1 }}
//   `
// }

/**
 * v-if v-else v-else-if 删除节点
 * 用注释节点占位  <!-- v-if -->
 * 
 * v-show 隐藏节点
 *
 * v-bind:参数 -》 插入JS表达式
 * v-on:事件名称 -》 绑定事件处理函数
 *      v-on:click="text(1)" => v-on:click="() => text(2)"
 * 
 * v-* 为了提示开发者这是一个Vue内置的attibute
 */

var str = 'I am Test'

var App = {
  data () {
    return {
      title: '标题1',
      linkIndex: 0,
      urls: [
        'www.baidu.com',
        'www.tmall.com',
        'www.jd.com'
      ],
      attr: 'href',
      eventName: 'click',
      titleAttr: 'tag',
      tag: 'h1',
      h_Attr: 'data-tag'
    }
  },
  methods: {
    changeIndex(index, event) {
      console.log(event)
      this.linkIndex = index
    },
    removeMyAttr() {
      this.h_Attr = null
    }
  },
  // template: `
  //   <div>
  //     <div>
  //       <p v-if="linkIndex === 0">
  //         <a v-bind:href="urls[0]">百度</a>
  //       </p>
  //       <p v-else-if="linkIndex === 1">
  //         <a v-bind:href="urls[1]">天猫</a>
  //       </p>
  //       <p v-else>
  //         <a v-bind:href="urls[2]">京东</a>
  //       </p>
  //     </div>
  //     <div>
  //       <button v-on:click="() => changeIndex(0)">百度</button>
  //       <button v-on:click="changeIndex(1)">天猫</button>
  //       <button v-on:click="changeIndex(2)">京东</button>
  //     </div>
  //   </div>
  // `
  // template: `
  //   <div>
  //     <div>
  //       <p v-show="linkIndex === 0">
  //         <a v-bind:href="urls[0]">百度</a>
  //       </p>
  //       <p v-show="linkIndex === 1">
  //         <a v-bind:href="urls[1]">天猫</a>
  //       </p>
  //       <p v-show="linkIndex === 2">
  //         <a v-bind:href="urls[2]">京东</a>
  //       </p>
  //     </div>
  //     <div>
  //       <button v-on:click="() => changeIndex(0)">百度</button>
  //       <button v-on:click="changeIndex(1)">天猫</button>
  //       <button v-on:click="changeIndex(2)">京东</button>
  //     </div>
  //   </div>
  // `
  template: `
    <div>
      <!-- 动态的属性名参数不能出现空格和引号，HTML 的合法属性名不能出现空格引号 -->
      <!-- <h1 v-bind:['data-' + titleAttr]="tag">{{ title }}</h1> -->
      <h1 v-bind:[h_Attr]="tag">{{ title }}</h1>
      <!-- null 作为属性名是无效的，不会渲染，因此可以利用该机制取消属性 -->
      <h1 v-bind:[null]="tag">{{ title }}</h1>
      <!-- 插值表达式无法访问全局变量 - 受限列表【vue-next/packages/shared/src/】 -->
      <h1>{{ str }}</h1>
      <div>
        <p v-show="linkIndex === 0">
          <a :[attr]="urls[0]">百度</a>
        </p>
        <p v-show="linkIndex === 1">
          <a :[attr]="urls[1]">天猫</a>
        </p>
        <p v-show="linkIndex === 2">
          <a :[attr]="urls[2]">京东</a>
        </p>
      </div>ß
      <div>
        <button @[eventName]="(event) => changeIndex(0, event)">百度</button>
        <button @[eventName]="changeIndex(1)">天猫</button>
        <button @[eventName]="changeIndex(2)">京东</button>
        <button @click="removeMyAttr">解除属性</button>
      </div>
    </div>
  `
}

createApp(App).mount('#app')